package info.hengha.blue.dao;

import info.hengha.blue.model.Category;
import info.hengha.blue.model.Term;
import info.hengha.blue.model.TermTaxonomy;
import info.hengha.utils.HibernateUtil;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.annotation.Resource;
import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.springframework.beans.factory.annotation.Autowired;

public class CategoryDao {
    //@Autowired
    private SessionFactory sessionFactory;

    //@Resource
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public void addCategory(Category category) {
        if (category != null) {
            /*
            HibernateUtil util = new HibernateUtil();
            Session session = util.getSession();
             */
            Session session = sessionFactory.openSession();
            session.getTransaction().begin();

            Query q = session.createQuery("from Term where name=:name");
            q.setString("name", category.getName());
            q.setMaxResults(1);
            Term t = (Term) q.uniqueResult();
            if (t != null) {
                // TODO: update model
            } else {
                t = new Term();
                t.setName(category.getName());
                t.setSlug(category.getSlug());
                session.save(t);
            }
            q = session.createQuery("from TermTaxonomy where termId=:termId");
            q.setInteger("termId", t.getId());
            q.setMaxResults(1);

            TermTaxonomy tt = (TermTaxonomy) q.uniqueResult();
            if (tt != null) {
                // TODO: update model
            } else {
                tt = new TermTaxonomy();
                tt.setTermId(t.getId());

                tt.setDescription(category.getDescription());
                tt.setParentId(category.getParentId());
                tt.setTaxonomy("category");

                session.save(tt);
            }
            category.setTermId(tt.getTermId());
            category.setId(tt.getId());
            session.getTransaction().commit();
            session.close();
        }
    }

    public Category getCategoryBySlug(String slug) {
        //HibernateUtil util = new HibernateUtil();
        //Session s = util.openSession();
        Session s = sessionFactory.openSession();
        s.getTransaction().begin();
        Query q = s.createQuery("from Term where slug=:slug");
        q.setString("slug", slug);
        q.setMaxResults(1);
        Term term = (Term) q.uniqueResult();
        if (term != null) {
            q = s.createQuery("from TermTaxonomy where termId=:termId");
            q.setInteger("termId", term.getId());
            q.setMaxResults(1);
            TermTaxonomy t = (TermTaxonomy) q.uniqueResult();

            Category category = new Category();
            if (t != null) {
                category.setId(t.getId());
                category.setParentId(t.getParentId());

                category.setTermId(t.getTermId());
                category.setDescription(t.getDescription());
                category.setName(term.getName());
                category.setSlug(term.getSlug());

                category.setChildren(getCategories(term.getId()));
                return category;
            }
            return null;
        }
        return null;
    }

    public List<Category> getCategories(int parentId) {
        //SessionFactory sf = pw.yitree.work.mmsh.HibernateUtil.getFactory();
        List<Category> categories;
        try (Session s = sessionFactory.openSession()) {
            s.getTransaction().begin();
            categories = new ArrayList<>();
            Query q = s.createQuery("from TermTaxonomy u where u.taxonomy='category' and u.parentId=:parentId");
            q.setInteger("parentId", parentId);
            List<TermTaxonomy> taxonomy = (List<TermTaxonomy>) (q.list());
            for (TermTaxonomy t : taxonomy) {
                Category category = new Category();
                category.setId(t.getId());
                category.setParentId(t.getParentId());
                category.setTermId(t.getTermId());
                category.setDescription(t.getDescription());

                q = s.createQuery("from Term where id=:id");
                q.setInteger("id", t.getTermId());
                q.setMaxResults(1);
                Term term = (Term) q.uniqueResult();

                category.setName(term.getName());
                category.setSlug(term.getSlug());

                category.setChildren(getCategories(category.getTermId()));
                categories.add(category);
            }
            s.getTransaction().commit();
        }
        return categories;
    }

    private Term findTerm(List<Term> terms, int id) {
        for (Term t : terms) {
            if (t.getId() == id) {
                return t;
            }
        }
        return null;
    }

    private Category findCategory(List<Category> categories, int id) {
        for (Category cat : categories) {
            if (cat.getId() == id) {
                return cat;
            }
        }
        return null;
    }

    public List<Category> getCategories() {
        //SessionFactory sf = pw.yitree.work.mmsh.HibernateUtil.getFactory();
        List<Category> categories;
        try (Session s = sessionFactory.openSession()) {
            s.getTransaction().begin();
            Criteria c = s.createCriteria(Term.class);
            List<Term> terms = c.list();
            c = s.createCriteria(TermTaxonomy.class)
                    .add(Restrictions.eq("taxonomy", "category"))
                    .addOrder(Order.asc("parentId"));
            List<TermTaxonomy> tts = c.list();
            categories = new ArrayList<Category>(2);
            for (TermTaxonomy tt : tts) {
                Category cat = new Category();
                cat.setId(tt.getId());
                cat.setTermId(tt.getTermId());
                cat.setParentId(tt.getParentId());
                Term t = findTerm(terms, tt.getTermId());
                cat.setName(t.getName());
                cat.setSlug(t.getSlug());
                if (tt.getParentId() == 0) {
                    cat.setChildren(new ArrayList<Category>());
                    categories.add(cat);
                } else {
                    Category parent = findCategory(categories, cat.getParentId());
                    parent.getChildren().add(cat);
                }
            }
            s.getTransaction().commit();
        }
        return categories;
    }
}
